package com.zbkj.crmeb.user.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.constants.Constants;
import com.crmeb.core.exception.CrmebException;
import com.zbkj.crmeb.store.dto.ChannelIntegralConfigDTO;
import com.zbkj.crmeb.store.service.ChannelIntegralConfigService;
import com.zbkj.crmeb.user.dao.UserIntegralSignDao;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.model.UserBill;
import com.zbkj.crmeb.user.model.UserIntegralSign;
import com.zbkj.crmeb.user.response.UserIntegralSignResponse;
import com.zbkj.crmeb.user.service.UserBillService;
import com.zbkj.crmeb.user.service.UserIntegralSignService;
import com.zbkj.crmeb.user.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Objects;

@Service
public class UserIntegralSignServiceImpl extends ServiceImpl<UserIntegralSignDao, UserIntegralSign> implements UserIntegralSignService {

    @Autowired
    private UserService userService;
    @Autowired
    private ChannelIntegralConfigService channelIntegralConfigService;
    @Autowired
    private UserBillService userBillService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserIntegralSignResponse sign() throws Exception {
        // 检查今天有没有签到过
        if (getSignStatus()){
            throw new CrmebException("今天已经签到");
        }
        UserIntegralSignResponse response = new UserIntegralSignResponse();
        // 签到的用户信息
        User user = userService.getInfoException();
        // 签到日期
        LocalDate now = LocalDate.now();
        // 商户设置的每天签到赠送积分
        ChannelIntegralConfigDTO integralConfig = channelIntegralConfigService.getIntegralConfig(user.getMerId());
        UserIntegralSign userIntegralSign = this.getOne(Wrappers.<UserIntegralSign>lambdaQuery()
                .eq(UserIntegralSign::getUid, user.getUid())
                .last("limit 1"));
        // 第一天签到
        if (Objects.isNull(userIntegralSign)) {
            userIntegralSign = new UserIntegralSign();
            userIntegralSign.setUid(user.getUid()).setOne(now);
            // 保存签到记录
            this.save(userIntegralSign);
            // 发放积分
            user.setIntegral(user.getIntegral().add(new BigDecimal(integralConfig.getOne())));
            userService.updateBase(user);
            // 积分变更进行记录
            saveIntegralBySign(user.getUid(), integralConfig.getOne(), user.getIntegral());
            // 返回签到数据
            response.setDay(1).setOne(now);
        } else {
            // 反射获取当前是第几天签到
            // 排除序列化id, 主键, 用户id
            int count = -3;
            String signDay = null;
            Field[] declaredFields = userIntegralSign.getClass().getDeclaredFields();
            for (Field fd : declaredFields) {
                count++;
                fd.setAccessible(true);
                if (Objects.isNull(fd.get(userIntegralSign))) {
                    fd.set(userIntegralSign, now);
                    signDay = fd.getName();
                    break;
                }
            }
            this.saveOrUpdate(userIntegralSign);
            PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(ChannelIntegralConfigDTO.class, signDay);
            // 商家签到天数设置的赠送积分
            Integer integral = (Integer) pd.getReadMethod().invoke(integralConfig);
            // 发放积分
            user.setIntegral(user.getIntegral().add(new BigDecimal(integral)));
            userService.updateBase(user);
            // 记录日志
            saveIntegralBySign(user.getUid(), integral, user.getIntegral());
            // 返回签到数据
            BeanUtils.copyProperties(userIntegralSign, response);
            response.setDay(count);
        }
        return response;
    }

    /**
     * 功能描述: 检查用户今日是否签到过
     * @Param: []
     * @Return: java.lang.Boolean
     * @Author: wangzh
     * @Date: 2023/3/2 15:06
     */
    @Override
    public Boolean getSignStatus() {
        // 用户信息
        User user = userService.getInfoException();
        // 用户签到记录
        UserIntegralSign userIntegralSign = this.getOne(Wrappers.<UserIntegralSign>lambdaQuery()
                .eq(UserIntegralSign::getUid, user.getUid())
                .last("limit 1"));
        try {
            Field[] declaredFields = userIntegralSign.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);
                Object o = field.get(userIntegralSign);
                // 检查今天有没有签到过
                if (o instanceof LocalDate) {
                    if (((LocalDate) o).compareTo(LocalDate.now()) == 0) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public UserIntegralSignResponse getSignRecord() {
        UserIntegralSignResponse response = new UserIntegralSignResponse();
        // 签到的用户信息
        User user = userService.getInfoException();
        UserIntegralSign userIntegralSign = this.getOne(Wrappers.<UserIntegralSign>lambdaQuery()
                .eq(UserIntegralSign::getUid, user.getUid())
                .last("limit 1"));
        if (Objects.isNull(userIntegralSign)) {
            return response;
        }
        BeanUtils.copyProperties(userIntegralSign, response);
        // 计算签到几天
        try {
            int count = 0;
            Field[] declaredFields = userIntegralSign.getClass().getDeclaredFields();
            for (Field f : declaredFields) {
                f.setAccessible(true);
                Object o = f.get(userIntegralSign);
                if (Objects.nonNull(o) && o instanceof LocalDate) {
                    count ++;
                }
            }
            response.setDay(count);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return response;
    }

    /**
     * 功能描述: 删除超过7天的签到记录
     * @Param: []
     * @Return: void
     * @Author: wangzh
     * @Date: 2023/3/9 11:18
     */
    @Override
    public void DeleteUserIntegralSignRecord() {
        // 截至时间 算上当天7天，所以减6
        LocalDate deadLine = LocalDate.now().minusDays(6);
        this.remove(Wrappers.<UserIntegralSign>lambdaQuery()
                .le(UserIntegralSign::getCreateTime, deadLine));
    }

    /**
     * 功能描述: 签到发放积分进行记录
     *
     * @Param: [uid, number, balance]
     * @Return: void
     * @Author: wangzh
     * @Date: 2023/3/2 10:23
     */
    private void saveIntegralBySign(Integer uid, Integer number, BigDecimal balance) {
        UserBill userBill = new UserBill();
        userBill.setUid(uid).setPm(1).setTitle("签到积分奖励").setCategory(Constants.USER_BILL_CATEGORY_INTEGRAL)
                .setType("sign").setNumber(new BigDecimal(number)).setBalance(balance)
                .setMark("签到积分奖励增加了" + number);
        userBillService.save(userBill);
    }

}
